package com.jetpackframework.retrofit;

import com.gwm.annotation.ftp.FTP;
import com.gwm.annotation.http.HTTP;
import com.gwm.annotation.http.HttpStream;
import com.gwm.annotation.http.JSONRequest;
import com.gwm.annotation.http.PostFormRequest;
import com.gwm.annotation.http.RequestBody;
import com.gwm.annotation.http.StreamPath;
import com.gwm.annotation.http.WebSocket;
import com.gwm.annotation.retrofit.HttpModel;
import com.gwm.annotation.router.AutoService;
import com.jetpackframework.ftp.FTPTask;
import com.jetpackframework.http.HttpTask;
import com.jetpackframework.retrofit.converter.FTPRequestConverter;
import com.jetpackframework.retrofit.converter.GetBuilderRequestConverter;
import com.jetpackframework.retrofit.converter.JsonRequestConverter;
import com.jetpackframework.retrofit.converter.PostFromRequestConverter;
import com.jetpackframework.retrofit.converter.RequestBodyRequestConverter;
import com.zhy.http.okhttp.builder.GetBuilder;
import com.zhy.http.okhttp.builder.PostFormBuilder;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

import okhttp3.Request;

/**
 * Created by Administrator on 2017/11/24.
 */
@AutoService(RetrofitInterface.class)
public class HttpInvocationHandler implements RetrofitInterface {
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if (method.isAnnotationPresent(HTTP.class)) {
            HttpTask.Builder params = addNetworkParams(method, args);
            Type type = method.getGenericReturnType();// 获取返回值类型
            if (type instanceof ParameterizedType) { // 判断获取的类型是否是参数类型
                Type[] typesto = ((ParameterizedType) type).getActualTypeArguments();// 强制转型为带参数的泛型类型，
                // getActualTypeArguments()方法获取类型中的实际类型，如map<String,Integer>中的
                // String，integer因为可能是多个，所以使用数组
                for (Type type2 : typesto) {
                    params.setResult(Class.forName(type2.toString().substring(6)));
                }
            }
            return ObservableHttp.http(params);
        }else if (method.isAnnotationPresent(FTP.class)){
            FTPTask task = addFtpTask(method,args);
            return ObservableFTP.ftp(task);
        }else {
            throw new IllegalAccessException("");
        }
    }

    private FTPTask addFtpTask(Method method, Object[] args) {
        FTPRequestConverter converter = getConverter(method);
        return converter.convert(method,args);
    }

    protected HttpTask.Builder addNetworkParams(Method method, Object[] args){
        HttpTask.Builder params = new HttpTask.Builder<>();
        if (method.isAnnotationPresent(HttpStream.class)){
            params.setStream(true);
            params.setStreamPath(method.getAnnotation(HttpStream.class).value());
            Annotation[][] annotations = method.getParameterAnnotations();
            for (int i = 0; i < annotations.length; i++) {     //i:第几个参数的注解
                if (annotations[i].length > 0) {
                    for (int j = 0; j < annotations[i].length; j++) {  //j: 第i个参数上的第j个注解
                        if(annotations[i][j] instanceof StreamPath) {
                            params.setStreamPath((String) args[i]);
                        }
                    }
                }
            }
        }
        if(method.isAnnotationPresent(HTTP.class)) {
            HTTP annotation = method.getAnnotation(HTTP.class);
            params.setMethod(annotation.way());
            params.setMessage(annotation.message());
            Converter converter = getConverter(method);
            if (method.isAnnotationPresent(PostFormRequest.class)){
                params.setPostFormBuild((PostFormBuilder) converter.convert(method,args));
            }else if (method.isAnnotationPresent(JSONRequest.class) || method.isAnnotationPresent(RequestBody.class)){
                params.setRequest((Request) converter.convert(method,args));
            }else if (annotation.way() == HTTP.WAY.GET){
                params.setGetBuilder((GetBuilder) converter.convert(method,args));
            }
        }else if (method.isAnnotationPresent(WebSocket.class)){
            WebSocket webSocket = method.getAnnotation(WebSocket.class);
            params.setUrl(webSocket.value());
        }else {
            throw new IllegalArgumentException("Unknown method annotation");
        }
        return params;
    }

    private <T extends Converter> T getConverter(Method method) {
        if (method.isAnnotationPresent(PostFormRequest.class)){
            return (T) PostFromRequestConverter.get();
        }else if (method.isAnnotationPresent(JSONRequest.class)){
            return (T) JsonRequestConverter.get();
        }else if (method.isAnnotationPresent(RequestBody.class)){
            return (T) RequestBodyRequestConverter.get();
        }else if (method.isAnnotationPresent(HTTP.class)){
            return (T) GetBuilderRequestConverter.get();
        }else if (method.isAnnotationPresent(FTP.class)){
            return (T) FTPRequestConverter.get();
        }
        return null;
    }

    @Override
    public Class<?> getAnnotation() {
        return HttpModel.class;
    }
}
